import copy
import heapq
import math
import random
import time

import networkx as nx
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import matplotlib.patches as mpatches
import itertools

plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

class WeightedGraphWithTasks:
    def __init__(self):
        self.graph = {}
        self.tasks = {}
        self.tasks_store={}
        self.Xc1=0.65
        self.Xl1=0.35
        self.Xc2=0.65
        self.Xl2=0.35
        self.diff1=0.2
        self.diff2=0.2
        self.distance_L = {}  # 各个节点到图书馆的最小距离
        self.predecessors_L = {}  # 回图书馆的前驱

    def modify_param(self,Xc1,Xl1,Xc2,Xl2,diff1,diff2):
        self.Xc1=Xc1
        self.Xl1=Xl1
        self.Xc2=Xc2
        self.Xl2=Xl2
        self.diff1=diff1
        self.diff2=diff2


    def add_edge(self, node1, node2, road_name, weight):
        if node1 not in self.graph:
            self.graph[node1] = {}
        if node2 not in self.graph:
            self.graph[node2] = {}
        self.graph[node1][node2] = {"road": road_name, "weight": weight}
        self.graph[node2][node1] = {"road": road_name, "weight": weight}

    def add_task(self, building, books_to_return, books_to_borrow):
        """添加还书和借书任务"""
        if not isinstance(books_to_return, int) or not isinstance(books_to_borrow, int):
            raise ValueError("书籍数量必须为整数")
        self.tasks[building] = {"return": books_to_return, "borrow": books_to_borrow}

    def dijkstra(self, start):
        """Dijkstra算法实现，返回从起点到各点的最短路径长度"""
        distances = {node: float('inf') for node in self.graph}
        distances[start] = 0
        queue = [(0, start)]
        predecessors = {node: None for node in self.graph}
        while queue:
            current_distance, current_node = heapq.heappop(queue)
            if current_distance > distances[current_node]:
                continue
            for neighbor, details in self.graph[current_node].items():
                distance = current_distance + details['weight']
                if distance < distances[neighbor]:
                    distances[neighbor] = distance
                    predecessors[neighbor] = current_node
                    heapq.heappush(queue, (distance, neighbor))
        return distances, predecessors  # 额外返回前驱可以找到最短路径

    def calculate_total_time(self, route, speed):
        total_time = 0
        for i in range(len(route) - 1):
            """If the next node is '充电站1' and it is not the last node in the route, skip this iteration"""
            if route[i + 1] == '充电站1' and i != len(route) - 2:
                continue
            """Check if the next node is a valid key in the graph"""
            if route[i + 1] in self.graph[route[i]]:
                total_time += self.graph[route[i]][route[i + 1]]['weight'] / speed
        return total_time

    # def generate_combinations(self,heap):
    #     result = []
    #     self.backtrack(heap, 0, [], [], result)
    #     return [combo for combo in result if combo[0] and combo[1]]
    #
    # def backtrack(self,heap, start, left, right, result):
    #     if start == len(heap):
    #         if left and right:
    #             result.append([left, right])
    #         return

        # 将当前元素加入左侧堆
        # self.backtrack(heap, start + 1, left + [heap[start]], right, result)
        #
        # # 将当前元素加入右侧堆
        # self.backtrack(heap, start + 1, left, right + [heap[start]], result)

    def find_best(self,current_nodeA, current_nodeB,index,route1,route2,isbeforel=True,islibrary=False):  # index是对下面add_route的情况分类0是A 1是B
        if(current_nodeA=='图书馆' or current_nodeB=='图书馆'):
            return '图书馆'
        distances_1, predecessors_1 = self.dijkstra(current_nodeB)
        distances_2, predecessors_2 = self.dijkstra(current_nodeA)
        cost_B = {}
        cost_A = {}
        min_costA = float('inf')
        max_costA = 0
        min_keyA = None  # 如果B都更好就先等着
        max_keyA = None
        min_costB = float('inf')
        max_costB = 0
        min_keyB = None  # 如果A都更好就先等着
        max_keyB = None
        for key in self.tasks:
            if isbeforel == False and self.tasks[key]['borrow'] ==0:
                continue
            if (self.tasks[key]['return']==0)and(isbeforel == True):
                continue
            cost_A[key] = (distances_2[key]*self.Xc1 + self.distance_L[key]*self.Xl1) / 8
            cost_B[key] = (distances_1[key]*self.Xc2 + self.distance_L[key]*self.Xl2) / 11
            if cost_A[key] < cost_B[key]:
                if cost_A[key] < min_costA:
                    min_costA = cost_A[key]
                    min_keyA = key
                if cost_B[key] > max_costB:
                    max_costB = cost_B[key]
                    max_keyB = key
            else:
                if cost_B[key] < min_costB:
                    min_costB = cost_B[key]
                    min_keyB = key
                if cost_A[key] > max_costA:
                    max_costA = cost_A[key]
                    max_keyA = key

        keys=[min_keyA,min_keyB,max_keyA,max_keyB]
        return_key=None
        if islibrary != True:  #在图书馆找最小值
            if keys[index]  in self.tasks:
                return_key = keys[index]
            else:
                return_key = keys[index^1]
        else:
            if keys[index+2]  in self.tasks:
                return_key =keys[index+2]  #往后两个位置的key是最大值的key
            else:
                return_key = keys[index^1 +2]
        if return_key:
            return return_key
        elif sum(self.tasks[key]['return'] for key in self.tasks)==0 and sum(self.tasks[key]['borrow'] for key in self.tasks)==0 :
            return '图书馆'
        else:
            print('错误')
            return '北辰楼'

    def find_route(self, current_node, next_node): # 寻找路径 无头尾
        d,p = self.dijkstra(current_node)
        temp = next_node
        route = [next_node]
        if current_node == next_node:
            return []
        i=1
        while p[temp] != current_node:
            route.insert(-i,p[temp])
            i+=1
            temp = p[temp]
        # route.insert(0, temp)
        return route


    def add_route(self,current_nodeA,current_nodeB):
        Task_route_A=['图书馆']
        Task_route_B=['图书馆']






        #操了

        while self.sum_dic(Task_route_B,'return')<10 and sum(self.tasks[key]['return'] for key in self.tasks) and current_nodeB!='图书馆': #对规划路线上的点的归还书求和
            key=self.find_best(current_nodeA, current_nodeB, 1,Task_route_A,Task_route_B,True,False)
            Task_route_B.insert(-1, key)
            current_nodeB = key
            if current_nodeB in self.tasks:
                self.tasks[current_nodeB]['return'] = 0
        if  self.sum_dic(Task_route_B,'return')>10 : #不为0在删
            if current_nodeB in self.tasks:
                self.tasks[current_nodeB]['return'] = self.sum_dic(Task_route_B, 'return') - 10

        while self.sum_dic(Task_route_A,'return')<10 and sum(self.tasks[key]['return'] for key in self.tasks) and current_nodeA!='图书馆': #对规划路线上的点的归还书求和
            key=self.find_best(current_nodeA, current_nodeB, 0,Task_route_A,Task_route_B,True,False)
            Task_route_A.insert(-1, key)
            current_nodeA = key
            if current_nodeA in self.tasks:
                self.tasks[current_nodeA]['return']=0
        if  self.sum_dic(Task_route_A,'return')>10 :
            if current_nodeA in self.tasks:
                self.tasks[current_nodeA]['return']=self.sum_dic(Task_route_A,'return')-10
                  # 大于10删掉倒数第二个，最后一个是图书馆


        current_nodeA=self.find_best(current_nodeA, current_nodeB, 0,Task_route_A,Task_route_B,True,True) #第一个是否不在图书馆前面了 第二个是是否在图书馆
        return_A=current_nodeA #去到的节点
        Task_route_A.insert(len(Task_route_A),return_A)
        if current_nodeA in self.tasks:
            self.tasks[current_nodeA]['borrow'] = 0
        locate_L=len(Task_route_A)-1
        while self.sum_dic(Task_route_A[locate_L-1:],'borrow')<10 and sum(self.tasks[key]['borrow'] for key in self.tasks) or self.sum_dic(Task_route_A[locate_L:],'borrow')-sum(self.tasks[key]['borrow'] for key in self.tasks)<0 and current_nodeA!='图书馆': #对规划路线上的点的借书求和
            key=self.find_best(current_nodeA, current_nodeB, 0,Task_route_A,Task_route_B,False,False)
            Task_route_A.insert(-1, key) #往前找在倒数第二个插入
            current_nodeA = key
            if current_nodeA in self.tasks:
                self.tasks[current_nodeA]['borrow'] = 0
        if  self.sum_dic(Task_route_A[locate_L-1:],'borrow')>10 : #比10大在删
            self.tasks[current_nodeA]['borrow'] = self.sum_dic(Task_route_A[locate_L-1:],'borrow')-10
        current_nodeB=self.find_best(current_nodeA, current_nodeB, 1,Task_route_A,Task_route_B,True,True) #第一个是否不在图书馆前面了 第二个是是否在图书馆
        return_B=current_nodeB #去到的节点
        Task_route_B.insert(len(Task_route_B),return_B)
        if current_nodeB in self.tasks:
            self.tasks[current_nodeB]['borrow'] = 0
        locate_L=len(Task_route_B)-1
        while (self.sum_dic(Task_route_B[locate_L:],'borrow')<10 and sum(self.tasks[key]['borrow'] for key in self.tasks)) and self.sum_dic(Task_route_B[locate_L:],'borrow')-sum(self.tasks[key]['borrow'] for key in self.tasks)<0 and current_nodeB!='图书馆': #对规划路线上的点的借书求和
            key=self.find_best(current_nodeA, current_nodeB, 1,Task_route_A,Task_route_B,False,False)
            Task_route_B.insert(-1, key) #往前找在倒数第二个插入
            current_nodeB = key
            if current_nodeB in self.tasks:
                self.tasks[current_nodeB]['borrow'] = 0
        if  self.sum_dic(Task_route_B[locate_L:],'borrow')>10 : #不为0在删
            self.tasks[current_nodeB]['borrow']=self.sum_dic(Task_route_B[locate_L:],'borrow')-10


        del Task_route_A[len(Task_route_A)-1]
        del Task_route_B[len(Task_route_B)-1]

        return return_A,return_B,Task_route_A,Task_route_B

    def sum_dic(self,route,kind='return'):
        sum =0
        for key in self.tasks_store.keys():
            if key in route:
                sum+= self.tasks_store[key][kind]
        return sum

    def combination(self,route):
        for j in range(len(route)-1):
            isbefore = True
            for i in range(len(route)):
                if route[i] == '图书馆':
                    i += 2
                    isbefore=False
                    continue
                if isbefore and route[i+1]!='图书馆':
                    if self.distance_L[route[i]]<self.distance_L[route[i+1]]:
                        route[i], route[i+1] = route[i+1], route[i]
                if isbefore==False and route[i-1]!='图书馆':
                    if self.distance_L[route[i]]<self.distance_L[route[i-1]]:
                        route[i], route[i-1] = route[i-1], route[i]
        return route



    def fit_route(self,route):
        if len(route) > 0:
            result = [route[0]]
        else:
            result=[]
        for i in range(len(route)-1):
            result[len(result):len(result)]=self.find_route(route[i],route[i+1])

        return result


    def plan_delivery_route(self, only_return=False):
        """规划路线，同时考虑归还和借用任务"""
        self.tasks_store = copy.deepcopy(self.tasks)
        route_B = ['充电站1']
        route_A = ['充电站2']
        current_nodeB = '充电站1'
        current_nodeA = '充电站2'
        if only_return:
            for key in  self.tasks:
                self.tasks[key]['borrow']=0
        self.distance_L,self.predecessors_L=self.dijkstra('图书馆')

        while self.tasks and( sum(self.tasks[key]['borrow'] for key in self.tasks) or sum(self.tasks[key]['return'] for key in self.tasks)):
            (current_nodeA, current_nodeB, T_routeA, T_routeB) = self.add_route(current_nodeA,current_nodeB)
            for key in T_routeA:
                if key in self.tasks and self.tasks[key]['return']==0 and (self.tasks[key]['borrow']==0 or only_return):
                    del self.tasks[key]
            for key in T_routeB:
                if key in self.tasks and self.tasks[key]['return']==0 and (self.tasks[key]['borrow']==0 or only_return):
                    del self.tasks[key]

            T_routeA=self.combination(T_routeA)
            T_routeB=self.combination(T_routeB)
            route_A.extend(T_routeA)
            route_B.extend(T_routeB)
        route_A.extend(['充电站2'])
        route_B.extend(['充电站1'])
        route_A=self.fit_route(route_A)
        route_B = self.fit_route(route_B)
        return route_B,route_A ,self.calculate_total_time(route_B, 10),self.calculate_total_time(route_A, 8)



# 初始化图和任务
graph_with_tasks = WeightedGraphWithTasks()

# 添加地点间的道路及权重
edges_road_weights = {
#第一列
    ('充电站1', '四美楼'): {'weight': 0.6},
    ('四美楼', '芳邻楼'): {'weight': 0.3},
    ('芳邻楼', '凌云楼'): {'weight': 1.1},
    ('凌云楼', '远山楼'): {'weight': 0.5},
    ('远山楼', '重霄楼'): {'weight': 0.8},
#第二列
    ('北辰楼', '弥津楼'): {'weight': 0.5},
    ('弥津楼', '映雪楼'): {'weight': 1.2},
    ('映雪楼', '高洁楼'): {'weight': 1.8},
    ('高洁楼', '南溟楼'): {'weight': 0.8},
    ('南溟楼', '长洲楼'): {'weight': 1.0},
#第三列
    ('秋水楼', '临川楼'): {'weight': 0.4},
    ('临川楼', '路口1'):  {'weight': 1.1},  #有缺地点
    ('路口1', '图书馆'):  {'weight': 2.2},
    ('图书馆', '景明楼'): {'weight': 0.7},
    ('景明楼', '清风楼'): {'weight': 1.0},
#第四列
    ('皓月楼', '耸翠楼'): {'weight': 0.9},
    ('耸翠楼', '朱华楼'): {'weight': 0.4},
    ('路口2', '绿竹楼'):  {'weight': 0.5}, #有缺地点
    ('绿竹楼', '沉壁楼'): {'weight': 0.6},
#第五列
    ('雅望楼', '朝晖楼'): {'weight': 0.3},
    ('朝晖楼', '流丹楼'): {'weight': 1.1},
    ('流丹楼', '俊采楼'): {'weight': 2.1},
    ('俊采楼', '汀兰楼'): {'weight': 0.8},
    ('汀兰楼', '兰亭楼'): {'weight': 1.1},
#第六列
    ('郁青楼', '星耀楼'): {'weight': 0.4},
    ('星耀楼', '万千楼'): {'weight': 0.9},
    ('万千楼', '东隅楼'): {'weight': 1.4},
    ('东隅楼', '长风楼'): {'weight': 0.6},
    ('长风楼', '充电站2'): {'weight': 0.5},
##第一行
    ('充电站1', '北辰楼'): {'weight': 0.7},
    ('北辰楼', '秋水楼'): {'weight': 0.7},
    ('秋水楼', '皓月楼'): {'weight': 0.5},
    ('皓月楼', '雅望楼'): {'weight': 1.1},
    ('雅望楼', '郁青楼'): {'weight': 0.5},
##第二行
    ('四美楼', '弥津楼'): {'weight': 0.6},
    ('弥津楼', '临川楼'): {'weight': 1.1},
    ('临川楼', '耸翠楼'): {'weight': 0.7},
    ('耸翠楼', '朝晖楼'): {'weight': 0.6},
    ('朝晖楼', '星耀楼'): {'weight': 0.9},
##第三行
    ('芳邻楼', '映雪楼'): {'weight': 1.5},
    ('映雪楼', '路口1'):  {'weight': 1.3},  #有缺地点
    ('路口1', '朱华楼'):  {'weight': 1.0},
    ('朱华楼', '流丹楼'): {'weight': 0.3},
    ('流丹楼', '万千楼'): {'weight': 0.8},
##第四行
    ('凌云楼', '高洁楼'): {'weight': 1.7},
    ('高洁楼', '图书馆'): {'weight': 0.7},
    ('图书馆', '路口2'):  {'weight': 0.4},  #有缺地点
    ('路口2', '俊采楼'):  {'weight': 0.8},
    ('俊采楼', '东隅楼'): {'weight': 0.7},
##第五行
    ('远山楼', '南溟楼'): {'weight': 2.0},
    ('南溟楼', '景明楼'): {'weight': 1.0},
    ('景明楼', '绿竹楼'): {'weight': 0.5},
    ('绿竹楼', '汀兰楼'): {'weight': 0.6},
    ('汀兰楼', '长风楼'): {'weight': 0.5},
##第六行
    ('重霄楼', '长洲楼'): {'weight': 0.7},
    ('长洲楼', '清风楼'): {'weight': 0.6},
    ('清风楼', '沉壁楼'): {'weight': 0.6},
    ('沉壁楼', '兰亭楼'): {'weight': 0.4},
    ('兰亭楼', '充电站2'): {'weight': 0.3},
}

# 使用add_edge方法添加边和权重到图中
for (node1, node2), details in edges_road_weights.items():
    graph_with_tasks.add_edge(node1, node2, f"{node1}到{node2}的路", details['weight'])

# 添加任务
 #第一列
graph_with_tasks.add_task('四美楼', 3, 0)  # 3本书要还，0本书要借
graph_with_tasks.add_task('芳邻楼', 4, 1)
graph_with_tasks.add_task('凌云楼', 2, 0)
graph_with_tasks.add_task('远山楼', 5, 2)
graph_with_tasks.add_task('重霄楼', 6, 0)
graph_with_tasks.add_task('北辰楼', 6, 2)
graph_with_tasks.add_task('弥津楼', 5, 0)
graph_with_tasks.add_task('映雪楼', 2, 0)
graph_with_tasks.add_task('高洁楼', 4, 0)
graph_with_tasks.add_task('南溟楼', 3, 1)
graph_with_tasks.add_task('长洲楼', 6, 0)
graph_with_tasks.add_task('秋水楼', 4, 3)
graph_with_tasks.add_task('临川楼', 3, 0)
graph_with_tasks.add_task('景明楼', 6, 0)
graph_with_tasks.add_task('清风楼', 2, 0)
graph_with_tasks.add_task('皓月楼', 7, 2)
 #第二列
graph_with_tasks.add_task('耸翠楼', 4, 0)
graph_with_tasks.add_task('朱华楼', 2, 3)
graph_with_tasks.add_task('绿竹楼', 5, 0)
graph_with_tasks.add_task('沉壁楼', 6, 0)
graph_with_tasks.add_task('雅望楼', 5, 2)
graph_with_tasks.add_task('朝晖楼', 3, 0)
graph_with_tasks.add_task('流丹楼', 8, 0)
graph_with_tasks.add_task('俊采楼', 3, 0)
graph_with_tasks.add_task('汀兰楼', 6, 2)
graph_with_tasks.add_task('兰亭楼', 2, 0)
graph_with_tasks.add_task('郁青楼', 3, 0)
graph_with_tasks.add_task('星耀楼', 4, 0)
graph_with_tasks.add_task('万千楼', 2, 2)
graph_with_tasks.add_task('东隅楼', 1, 0)
graph_with_tasks.add_task('长风楼', 5, 0)
 #自己加的第三列
# graph_with_tasks.add_task('路口1', 0, 0)
# graph_with_tasks.add_task('路口2', 0, 0)
# graph_with_tasks.add_task('充电站1', 0, 0)
# graph_with_tasks.add_task('充电站2', 0, 0)
# graph_with_tasks.add_task('图书馆', 0, 0)

# 规划配送路线
robot_specs = {
    'A': {'start_node': '充电站2', 'max_capacity': 10, 'speed': 8},
    'B': {'start_node': '充电站1', 'max_capacity': 10, 'speed': 10},
}

graph_with_tasks.modify_param(0.5027143173989218 ,1-0.5027143173989218,0.7416798926471098,1-0.7416798926471098,0.1,0.1)
route_B,route_A,T_B,T_A=graph_with_tasks.plan_delivery_route()#找到的最优参数
print(route_A)
print(T_A)
print(route_B)
print(T_B)


def f(Xc1,Xc2,diff1,diff2,graph_with_tasks):
    #这里task要重新添加，so整合一下前面写的输入
    graph_with_tasks.add_task('四美楼', 3, 0)  # 3本书要还，0本书要借
    graph_with_tasks.add_task('芳邻楼', 4, 1)
    graph_with_tasks.add_task('凌云楼', 2, 0)
    graph_with_tasks.add_task('远山楼', 5, 2)
    graph_with_tasks.add_task('重霄楼', 6, 0)
    graph_with_tasks.add_task('北辰楼', 6, 2)
    graph_with_tasks.add_task('弥津楼', 5, 0)
    graph_with_tasks.add_task('映雪楼', 2, 0)
    graph_with_tasks.add_task('高洁楼', 4, 0)
    graph_with_tasks.add_task('南溟楼', 3, 1)
    graph_with_tasks.add_task('长洲楼', 6, 0)
    graph_with_tasks.add_task('秋水楼', 4, 3)
    graph_with_tasks.add_task('临川楼', 3, 0)
    graph_with_tasks.add_task('景明楼', 6, 0)
    graph_with_tasks.add_task('清风楼', 2, 0)
    graph_with_tasks.add_task('皓月楼', 7, 2)
    # 第二列
    graph_with_tasks.add_task('耸翠楼', 4, 0)
    graph_with_tasks.add_task('朱华楼', 2, 3)
    graph_with_tasks.add_task('绿竹楼', 5, 0)
    graph_with_tasks.add_task('沉壁楼', 6, 0)
    graph_with_tasks.add_task('雅望楼', 5, 2)
    graph_with_tasks.add_task('朝晖楼', 3, 0)
    graph_with_tasks.add_task('流丹楼', 8, 0)
    graph_with_tasks.add_task('俊采楼', 3, 0)
    graph_with_tasks.add_task('汀兰楼', 6, 2)
    graph_with_tasks.add_task('兰亭楼', 2, 0)
    graph_with_tasks.add_task('郁青楼', 3, 0)
    graph_with_tasks.add_task('星耀楼', 4, 0)
    graph_with_tasks.add_task('万千楼', 2, 2)
    graph_with_tasks.add_task('东隅楼', 1, 0)
    graph_with_tasks.add_task('长风楼', 5, 0)
    graph_with_tasks.modify_param(Xc1,1-Xc1,Xc2,1-Xc2,diff1,diff2)
    route_B,route_A,T_B,T_A=graph_with_tasks.plan_delivery_route()



    

    return max(T_B,T_A)
print(f(0.5027143173989218 ,0.7416798926471098,0.1,  0.1,graph_with_tasks))

hi=1
lo=0

alf=0.95
T=100

def new(Xc1,Xc2,diff1,diff2):
    result=[Xc1,Xc2,diff1,diff2]
    index_to_modify = random.randint(0, 1)
    rand =random.uniform(-1, 1)
    min_val=result[index_to_modify]-T/100
    max_val=result[index_to_modify]+T/100
    result[index_to_modify] = T * rand/100+result[index_to_modify]
    if result[index_to_modify]>lo or result[index_to_modify]<hi:
        result[index_to_modify]=(result[index_to_modify] - min_val) / (max_val - min_val)
    return result
#p函数
def p(Xc1,Xc2,diff1,diff2,Xc10,Xc20,diff10,diff20,graph_with_tasks):
    return math.exp(-abs(f(Xc10,Xc20,diff10,diff20,graph_with_tasks)-f(Xc1,Xc2,diff1,diff2,graph_with_tasks))/T)

Xc1=0.65
Xc2=0.65
diff1=0.2
diff2=0.2
iteration_times = []
iteration =0
def main():
    global Xc1,Xc2,diff1,diff2
    global T
    global graph_with_tasks
    global iteration
    global iteration_times
    while T>0.001:
        print(T)
        print('{}'.format((Xc1,Xc2,diff1,diff2)))
        for i in range(500):
            iteration+=1
            iteration_times.append(f(Xc1,Xc2,diff1,diff2,graph_with_tasks))
            f(Xc1, Xc2, diff1, diff2, graph_with_tasks)
            Xc10,Xc20,diff10,diff20=new(Xc1,Xc2,diff1,diff2)
            if f(Xc10,Xc20,diff10,diff20,graph_with_tasks)<=f(Xc1,Xc2,diff1,diff2,graph_with_tasks):
                Xc1,Xc2,diff1,diff2=Xc10,Xc20,diff10,diff20
            else:
                if random.random()<=p(Xc1,Xc2,diff1,diff2,Xc10,Xc20,diff10,diff20,graph_with_tasks):
                    Xc1,Xc2,diff1,diff2=Xc10,Xc20,diff10,diff20
                else:
                    continue
        T=T*alf
    print('最小值为：{}'.format(f(Xc1,Xc2,diff1,diff2,graph_with_tasks)))
    print('最的参数为：{}'.format((Xc1,Xc2,diff1,diff2)))


main()

#
node_positions = {
    #第一列
'充电站1': (0, 5),
'四美楼': (0, 4),
'芳邻楼': (0, 3),
'凌云楼': (0, 2),
'远山楼': (0, 1),
'重霄楼': (0, 0),
    #第二列
'北辰楼': (1, 5),
'弥津楼': (1, 4),
'映雪楼': (1, 3),
'高洁楼': (1, 2),
'南溟楼': (1, 1),
'长洲楼': (1, 0),
    #第三列
'秋水楼': (2, 5),
'临川楼': (2, 4),
'路口1':  (2, 3),
'图书馆': (2, 2),
'景明楼': (2, 1),
'清风楼': (2, 0),
    #第四列
'皓月楼': (3, 5),
'耸翠楼': (3, 4),
'朱华楼': (3, 3),
'路口2':  (3, 2),
'绿竹楼': (3, 1),
'沉壁楼': (3, 0),
    #第五列
'雅望楼': (4, 5),
'朝晖楼': (4, 4),
'流丹楼': (4, 3),
'俊采楼': (4, 2),
'汀兰楼': (4, 1),
'兰亭楼': (4, 0),
    #第六列
'郁青楼': (5, 5),
'星耀楼': (5, 4),
'万千楼': (5, 3),
'东隅楼': (5, 2),
'长风楼': (5, 1),
'充电站2': (5, 0),
}


# 绘制图形
# def visualize_graph(graph_with_tasks):
#     G = nx.Graph()
#
#     # 添加边和权重到网络X图中
#     for node1, neighbors in graph_with_tasks.graph.items():
#         for node2, details in neighbors.items():
#             G.add_edge(node1, node2, weight=details['weight'])
#
#     # 设置节点位置
#     pos = node_positions
#
#     # 绘制无向图
#     nx.draw_networkx_nodes(G, pos, node_size=800, node_color='skyblue', edgecolors='black', linewidths=1.4)
#     nx.draw_networkx_edges(G, pos, edgelist=G.edges(), edge_color='gray', width=1.5, alpha=0.6)
#     nx.draw_networkx_labels(G, pos, font_size=7, font_family="sans-serif", font_color='black')
#
#     # 显示权重
#     labels = nx.get_edge_attributes(G, 'weight')
#     nx.draw_networkx_edge_labels(G, pos, edge_labels=labels, font_color='red')
#
#     plt.axis('off')
#     plt.title('送货路线图', fontsize=20)
#     plt.show()
#
# # 在规划完路线后，调用visualize_graph函数进行可视化
# visualize_graph(graph_with_tasks)




# #动画显示
#
# edge_colors = {}
# arrows = []
#
# def update(num, G, pos, edges_A, edges_B, line_A, line_B):
#     global arrows
#
#     # 清除之前的线条
#     line_A.set_data([], [])
#     line_B.set_data([], [])
#
#     # 删除旧的箭头
#     while arrows:
#         arrows.pop().remove()
#
#     # 更新每一帧的路线
#     for edge in edges_A[num:num+1]:
#         color = 'blue'
#         line_A.set_color(color)
#         line_A.set_data([pos[edge[0]][0], pos[edge[1]][0]], [pos[edge[0]][1], pos[edge[1]][1]])
#         arrow = plt.arrow(pos[edge[0]][0], pos[edge[0]][1], pos[edge[1]][0] - pos[edge[0]][0], pos[edge[1]][1] - pos[edge[0]][1], color=color, shape='full', lw=0, length_includes_head=True, head_width=.2)
#         arrows.append(arrow)
#
#     for edge in edges_B[num:num+1]:
#         color = 'red'
#         line_B.set_color(color)
#         line_B.set_data([pos[edge[0]][0], pos[edge[1]][0]], [pos[edge[0]][1], pos[edge[1]][1]])
#         arrow = plt.arrow(pos[edge[0]][0], pos[edge[0]][1], pos[edge[1]][0] - pos[edge[0]][0], pos[edge[1]][1] - pos[edge[0]][1], color=color, shape='full', lw=0, length_includes_head=True, head_width=.2)
#         arrows.append(arrow)
#
#     return line_A, line_B
#
# def visualize_routes(graph_with_tasks, route_A, route_B):
#     G = nx.Graph()
#
#     # 添加边和权重到网络X图中
#     for node1, neighbors in graph_with_tasks.graph.items():
#         for node2, details in neighbors.items():
#             G.add_edge(node1, node2, weight=details['weight'])
#
#     # 设置节点位置
#     pos = node_positions
#
#     # 绘制无向图
#     nx.draw_networkx_nodes(G, pos, node_size=800, node_color='skyblue', edgecolors='black', linewidths=1.4)
#     nx.draw_networkx_edges(G, pos, edgelist=G.edges(), edge_color='gray', width=1.5, alpha=0.6)
#     nx.draw_networkx_labels(G, pos, font_size=7, font_family="sans-serif", font_color='black')
#
#     # 显示权重
#     labels = nx.get_edge_attributes(G, 'weight')
#     nx.draw_networkx_edge_labels(G, pos, edge_labels=labels, font_color='red')
#
#     # 将路线转换为边的列表
#     edges_A = [(route_A[i], route_A[i + 1]) for i in range(len(route_A) - 1)]
#     edges_B = [(route_B[i], route_B[i + 1]) for i in range(len(route_B) - 1)]
#
#     # 创建两条路线的线对象
#     line_A, = plt.plot([], [], color='blue', linewidth=2.5, alpha=0.6)
#     line_B, = plt.plot([], [], color='red', linewidth=2.5, alpha=0.6)
#
#     # 创建动画
#     ani = animation.FuncAnimation(plt.gcf(), update, frames=len(edges_A), fargs=(G, pos, edges_A, edges_B, line_A, line_B), interval=500)
#
#     plt.axis('off')
#     plt.title('送货路线图', fontsize=20)
#     plt.show()
#
# # 在规划完路线后，调用visualize_routes函数进行可视化
# visualize_routes(graph_with_tasks, route_A, route_B)



  #定义要执行的迭代次数


# for i in range(iterations):
#     _, _, time_A, time_B = graph_with_tasks.plan_delivery_route()
#     iteration_times.append(max(time_A, time_B))  # 取两个机器人中花费时间较长的那个
def plot_iteration_times(iteration_times):
    plt.figure(figsize=(10, 6))
    plt.plot(iteration_times, marker='o')
    plt.title('迭代次数与时间关系', fontsize=20)
    plt.xlabel('迭代次数')
    plt.ylabel('时间 (s)')
    plt.grid(True)
    plt.show()

# 可视化
plot_iteration_times(iteration_times)